#ifndef NIXONBOT_CORE_BNCS_PROTOCOL_MESSAGEFACTORY_H_
#define NIXONBOT_CORE_BNCS_PROTOCOL_MESSAGEFACTORY_H_

namespace nixonbot {
namespace core {
namespace bncs {
namespace protocol {

/* This must be placed at the top of every client message
 * class declaration, so that it is included in the factory
 * lookup table. */
#define BNCS_MESSAGE_CLIENT_REGISTER(cls_name, id) \
	private: static MessageFactoryClientRegistrar reg ((id), new cls_name())
	
/* This must be placed at the top of every server message
 * class declaration, so that it is included in the factory
 * lookup table. */
#define BNCS_MESSAGE_SERVER_REGISTER(cls_name, id) \
	private: static MessageFactoryServerRegistrar reg ((id), new cls_name())

/* Registers a Message object with the MessageFactory at
 * static initialization. This object will be registered
 * as a client message. */
class MessageFactoryClientRegistrar
{
public:
	MessageFactoryClientRegistrar(int id, Message* msg);
};

/* Registers a Message object with the MessageFactory at
 * static initialization. This object will be registered
 * as a server message. */
class MessageFactoryServerRegistrar
{
public:
	MessageFactoryServerRegistrar(int id, Message* msg);
};

/* Creates a Message object based on packet ID. */
class MessageFactory
{
private:
	/* Stores a mapping from client packet IDs to client message objects. */
	static QHash<int, Message*> clientMessageTable;
	
	/* Stores a mapping from server packet IDs to server message objects. */
	static QHash<int, Message*> serverMessageTable;

public:
	/* Creates a new client message for the given packet ID and returns
	 * a reference to it. */
	static Message* newClientMessage(int id);
	
	/* Creates a new server message for the given packet ID and returns
	 * a reference to it. */
	static Message* newServerMessage(int id);
	
private:
	/* Instantiation of this class is not allowed. */
	MessageFactory();
	~MessageFactory();

friend class MessageFactoryRegistrar;
};

}
}
}
}

#endif /* NIXONBOT_CORE_BNCS_PROTOCOL_MESSAGEFACTORY_H_ */
